package com.example.web.websystem.token.manage;

import com.alibaba.fastjson.JSON;
import com.example.web.websystem.response.BusinessError;
import com.example.web.websystem.response.GlobalCodeEnum;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;

/**
 * token 操作
 * <p>
 * Created by YangGang on 2021/3/8 17:57。
 */
public class TokenHandle {
    //request中保存token的字段
    private static String key = "Authentication";
    //秘钥
    private static String secret = "sif3%uf_ie12$%^$";
    //有效时间（秒）
    private static long expire = 3600L * 24 * 3;
    //claimName
    private static String claimName = "TOKEN_OBJECT_87SFDNF7IY78SDHFKHDFSD453423DFDF3";


    public static String createToken(Object obj) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(claimName, JSON.toJSONString(obj));
        return Jwts.builder()
                .setClaims(bodyMap)
                .setExpiration(new Date(System.currentTimeMillis() + expire * 1000L))
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    public static TokenObject getCurrentTokenObject() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return parse(getToken(request));
    }

    public static String getToken(HttpServletRequest request) {
        return request.getHeader(key);
    }

    public static TokenObject parse(String token) {
        return parsing(token, TokenObject.class);
    }

    /**
     * 解析token
     *
     * @param token
     * @param clazz
     * @param <T>
     * @return
     */
    private static <T> T parsing(String token, Class<T> clazz) {
        if (token == null) return null;
        Claims claims;
        T tokenObject;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
            String userJson = claims.get(claimName, String.class);
            tokenObject = JSON.parseObject(userJson, clazz);
        } catch (Error e) {
            throw new BusinessError(GlobalCodeEnum.TOKEN_INVALID);
        }
        return tokenObject;
    }


    /**
     * 如果校验通过返回null，不通过返回校验的错误code信息
     *
     * @param token
     * @return
     */
    public static GlobalCodeEnum verifyToken(String token) {
        GlobalCodeEnum result = null;
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
            final Date exp = claims.getExpiration();
            if (exp.before(new Date())) {
                result = GlobalCodeEnum.TOKEN_EXPIRED;
            }
        } catch (Exception e) {
            result = GlobalCodeEnum.TOKEN_INVALID;
        }
        return result;
    }

}
